package com.ypay.apppay;

import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.WindowManager;
import android.widget.TextView;
import android.widget.Toast;

import com.alipay.sdk.app.PayTask;
import com.tencent.mm.sdk.modelpay.PayReq;
import com.tencent.mm.sdk.openapi.IWXAPI;
import com.tencent.mm.sdk.openapi.WXAPIFactory;

import java.io.File;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.concurrent.TimeUnit;

import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.functions.Consumer;
import io.reactivex.schedulers.Schedulers;
import okhttp3.Cache;
import okhttp3.CacheControl;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;
import retrofit2.http.GET;
import retrofit2.http.Query;
import ypay.com.wxpay.R;


/**
 * Created on 2018-03-09 09:33.
 * 网络请求service工厂类
 *
 * @author sunzh
 */

/**
 * SELECT
 * <p>
 * FROM
 * wechat_account
 * WHERE
 * package_name ='com.yzhn.demo'
 * AND  use_local ='video'
 * AND  STATUS ='1'
 */
public class ServiceFactory {

    private static final int TIME_OUT = 20;
    private final static int PAY_NATIVE = 1;
    private final static int PAY_CLOSE = 3;
    private static  String JAVA_SERVER_URL ;
    private static final int cacheSize = 10 * 1024 * 1024;
    private static final String USER_TOKEN = "ef8c39dc5a775990a864fa9e838cec69";
    private static String PACKET_NAME;
    private static IWXAPI wechatAPI;
    private static final String ALIPAY_SUCESS = "9000";

    public static boolean isSucess(Message msg) {
        // 判断resultStatus 为9000则代表买单成功
        return TextUtils.equals(((PayResult) msg.obj).getResultStatus(), ALIPAY_SUCESS);
    }

    /**
     * 用于请求服务器接口
     */
    private static OkHttpClient httpClient;
    private static Cache cache;
    private static boolean IS_DEBUG;

    public static IWXAPI getWXAPI() {
        return wechatAPI;
    }
    public static void init(Context context,String payUrl) {
        init(context,false,payUrl);
    }
    public static void init(Context context, boolean isDebug,String payUrl) {
        wechatAPI = WXAPIFactory.createWXAPI(context, null);
        cache = new Cache(new File(context.getApplicationContext().getCacheDir(), "TongChengResponses"), cacheSize);
        IS_DEBUG = isDebug;
        PACKET_NAME = context.getApplicationContext().getPackageName();
        JAVA_SERVER_URL=payUrl;
        initHttpClient();
    }

    public static void payWechat(Context context, String platform
            , String totalAmount) {
        payWechat(context, "1", "2", platform, totalAmount, "test", "no_notifyUrl", PACKET_NAME);
    }

    public static void payAlipay(Context context, String platform
            , String totalAmount) {

        payAlipay(context, platform, totalAmount, null);
    }

    public static void payAlipay(Context context, String platform
            , String totalAmount, Handler handler) {

        payAlipay(context, "1", "2", platform, totalAmount, "test", "no_notifyUrl", PACKET_NAME, handler);
    }

    public static void payWechat(Context context, String uid, String source, String platform
            , String totalAmount, String body, String notifyUrl, String packageName) {
        MLoadingDialog.showLoadingDialog(context);
        createService(ApiService.class)
                .wechatBooking(uid, source, platform, totalAmount, body, notifyUrl, packageName)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Consumer<WechatBookingResponseBean>() {
                    @Override
                    public void accept(WechatBookingResponseBean responseBean) throws Exception {
                        MLoadingDialog.cancelLoadingDialog(context);
                        if (responseBean == null) {
                            Toast.makeText(context, "支付信息为空", Toast.LENGTH_SHORT).show();
                        } else {
                            if (responseBean.getPay_type() == PAY_NATIVE) {//原生
                                startWechatPay(responseBean.getAppid(), responseBean.getPartnerid(), responseBean.getPrepay_id(),
                                        responseBean.getWechat_key(), responseBean.getNoncestr(), responseBean.getSign(), responseBean.getTimestamp());
                            } else if (responseBean.getPay_type() == PAY_CLOSE) {
                                //关闭
                                Toast.makeText(context, "微信支付通道暂时关闭，请使用支付宝支付", Toast.LENGTH_SHORT).show();
                            } else {
                                Toast.makeText(context, "支付错误，请重试", Toast.LENGTH_SHORT).show();
                            }
                        }
                    }
                }, new Consumer<Throwable>() {
                    @Override
                    public void accept(Throwable throwable) throws Exception {
                        MLoadingDialog.cancelAllLoadingDialog();
                        Toast.makeText(context, throwable.getMessage(), Toast.LENGTH_SHORT).show();

                    }
                });
    }

    public static void payAlipay(Context context, String uid, String source, String platform
            , String totalAmount, String body, String notifyUrl, String packageName, Handler handler) {
        MLoadingDialog.showLoadingDialog(context);
        createService(ApiService.class)
                .aliPayBooking(uid, source, platform, totalAmount, body, notifyUrl, packageName)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Consumer<WechatBookingResponseBean>() {
                    @Override
                    public void accept(WechatBookingResponseBean responseBean) throws Exception {
                        if (responseBean == null) {
                            Toast.makeText(context, "支付信息为空", Toast.LENGTH_SHORT).show();
                        } else {
                            if (responseBean.getPay_type() == PAY_NATIVE) {//原生
                                startAliPay(context, responseBean.getOrderInfo(), handler);
                            } else if (responseBean.getPay_type() == PAY_CLOSE) {
                                //关闭
                                Toast.makeText(context, "支付宝支付通道暂时关闭，请使用微信宝支付", Toast.LENGTH_SHORT).show();
                            } else {
                                Toast.makeText(context, "支付错误，请重试", Toast.LENGTH_SHORT).show();
                            }
                        }
                    }
                }, new Consumer<Throwable>() {
                    @Override
                    public void accept(Throwable throwable) throws Exception {
                        MLoadingDialog.cancelAllLoadingDialog();
                        Toast.makeText(context, throwable.getMessage(), Toast.LENGTH_SHORT).show();

                    }
                });
    }

    private static void startAliPay(Context context, String orderInfo, final Handler handler) {

        new Thread(new Runnable() {

            @Override
            public void run() {
                Looper.prepare();
                MLoadingDialog.cancelLoadingDialog(context);
                PayTask alipay = new PayTask((Activity) context);
                Map<String, String> result = alipay.payV2(orderInfo, true);
                PayResult payResult = new PayResult(result);
                if (IS_DEBUG) {
                    Toast.makeText(context, payResult.getResult() + "[" + payResult.getResultStatus() + "]", Toast.LENGTH_SHORT).show();

                }

                Message msg = new Message();
                msg.obj = payResult;

                if (handler != null) {
                    handler.sendMessage(msg);
                } else if (isSucess(msg)) {
                    Toast.makeText(context, "支付成功", Toast.LENGTH_SHORT).show();
                }
                Looper.loop();// 进入loop中的循环，查看消息队列
            }
        }).start();
    }

    private static void initHttpClient() {
        OkHttpClient.Builder builder = new OkHttpClient.Builder()
                .readTimeout(TIME_OUT, TimeUnit.SECONDS)
                .connectTimeout(TIME_OUT, TimeUnit.SECONDS)

                .addInterceptor(chain -> {
                    Request request = chain.request();
                    CacheControl.Builder cacheBuilder = new CacheControl.Builder();
                    cacheBuilder.maxAge(0, TimeUnit.SECONDS);
                    cacheBuilder.maxStale(365, TimeUnit.DAYS);


                    request = request.newBuilder()
                            .addHeader("token", USER_TOKEN)
                            .build();

                    Response originalResponse = chain.proceed(request);

                    int maxAge = 0;
                    return originalResponse.newBuilder()
                            .removeHeader("Pragma")
                            .header("Cache-Control", "public ,max-age=" + maxAge)
                            .build();

                }).cache(cache);
        if (IS_DEBUG) {
            builder.addInterceptor(IS_DEBUG ? new HttpLoggingInterceptor(message
                    -> Log.e("zyfff", "" + "收到响应:" + message)).setLevel(HttpLoggingInterceptor.Level.BODY) :
                    new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.NONE)
            );
        }
        httpClient = builder.build();

    }


    private static <T> T createService(Class<T> serviceClazz) {
        Retrofit retrofit = new Retrofit.Builder()
                .client(httpClient)
                .baseUrl(JAVA_SERVER_URL)
                // 返回Gson解析对象
                .addConverterFactory(GsonConverterFactory.create())
//                .addConverterFactory(ResponseConverterFactory.create())
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .build();

        return retrofit.create(serviceClazz);
    }

    /**
     * 客户端调起支付，预下单由服务器下
     *
     * @param appId
     * @param mId
     * @param prepayId
     */
    private static void startWechatPay(String appId, String mId, String prepayId, String wechat_key, String noncestr, String sign, String timestamp) {
        wechatAPI.unregisterApp();
        wechatAPI.registerApp(appId);
        String nonceStr = noncestr;
        String time = timestamp;

        SortedMap<Object, Object> parameters = new TreeMap<Object, Object>();
        parameters.put("appid", appId);
        parameters.put("partnerid", mId);
        parameters.put("prepayid", prepayId);
        parameters.put("package", "Sign=WXPay");
        parameters.put("noncestr", nonceStr);
        parameters.put("timestamp", time);

        String mySign = sign;

        // 调起支付
        PayReq request = new PayReq();
        request.appId = appId;
        request.partnerId = mId;
        request.prepayId = prepayId;
        request.packageValue = "Sign=WXPay";
        request.nonceStr = nonceStr;
        request.timeStamp = time;
        request.sign = mySign;
        request.extData = "app data";
        wechatAPI.sendReq(request);
    }


}

interface ApiService {


    @GET("recharge/api/wechatBooking")
    Observable<WechatBookingResponseBean> wechatBooking(@Query("uid") String uid, @Query("source") String source, @Query("platform") String platform
            , @Query("totalAmount") String totalAmount, @Query("body") String body, @Query("notifyUrl") String notifyUrl, @Query("packageName") String packageName);

    @GET("recharge/api/aliPayBooking")
    Observable<WechatBookingResponseBean> aliPayBooking(@Query("uid") String uid, @Query("source") String source, @Query("platform") String platform
            , @Query("totalAmount") String totalAmount, @Query("body") String body, @Query("notifyUrl") String notifyUrl, @Query("packageName") String packageName);

}

class MLoadingDialog extends Dialog {
    private static HashMap<Context, MLoadingDialog> dialogs = new HashMap<Context, MLoadingDialog>();
    private TextView content;

    private MLoadingDialog(Context context) {
        super(context, R.style.LoadingDialogStyle);
//        setOwnerActivity((Activity) context);// 设置dialog全屏显示

        WindowManager.LayoutParams lp = getWindow().getAttributes();
        lp.dimAmount = 0.15f; // 设置进度条周边暗度（0.0f ~ 1.0f）
        getWindow().setAttributes(lp);
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);

        this.setCanceledOnTouchOutside(false);
//        this.setContentView(R.layout.loading_dialog);

        LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        View view = inflater.inflate(R.layout.mloading_dialog, null);
        content = (TextView) view.findViewById(R.id.dialog_content_tv);
        this.setContentView(view);
    }

    private MLoadingDialog(Context context, int theme) {
        super(context, theme);
    }

    public synchronized static MLoadingDialog obtainLoadingDialog(Context context) {
        MLoadingDialog dialog = dialogs.get(context);
        if (null == dialog) {
            dialog = new MLoadingDialog(context);
            dialogs.put(context, dialog);
        }
        return dialog;
    }

    public static void showLoadingDialog(Context context) {
        showLoadingDialog(context, "正在加载");
    }

    public static void showLoadingDialog(Context context, String content) {
        if (null == content || content.equals("")) {
            showLoadingDialog(context);
            return;
        }
        MLoadingDialog dialog = MLoadingDialog.obtainLoadingDialog(context);
        dialog.getContent().setText(content);
        try {
            dialog.show();
        } catch (Throwable ex) {
            ex.printStackTrace();
        }
    }

    public static void cancelLoadingDialog(Context context) {
        try {
            MLoadingDialog.obtainLoadingDialog(context).cancel();
            dialogs.remove(context);
        } catch (IllegalArgumentException e) {
        }
    }

    public static void cancelAllLoadingDialog() {
        try {
            Set<Context> set = dialogs.keySet();
            for (Iterator iter = set.iterator(); iter.hasNext(); ) {
                MLoadingDialog.obtainLoadingDialog((Context) iter.next()).cancel();
                iter.remove();
            }
            dialogs.clear();
        } catch (IllegalArgumentException ex) {
        }

    }

    public TextView getContent() {
        return content;
    }

    public void setContent(TextView content) {
        this.content = content;
    }
}

